package com.junming.learning.generics;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
 * @author zhangfei
 * upper bounded wildcards: an upper bounded wildcard restricts the unknown type to be a specific type or a subtype of that type
 * 
 * unbounded wildcards: 
 * There are two scenarios where an unbounded wildcard is a useful approach:
 * 1.If you are writing a method that can be implemented using functionality provided in the Object class.
 * 2.When the code is using methods in the generic class that don't depend on the type parameter. 
 * For example, List.size or List.clear. In fact, Class<?> is so often used because most of the methods in Class<T> do not depend on T.
 * 
 * lower bounded wildcards: a lower bounded wildcard restricts the unknown type to be a specific type or a super type of that type
 */

public class WildCard {
	public static  double process1(List<? extends Number> list) {
		//上边界符List<? extends Number> 接受 Number或Number子类的List
		BigDecimal sum = BigDecimal.ZERO;
		for(Number elem : list) {
			BigDecimal bd = BigDecimal.valueOf(elem.doubleValue());
			sum = sum.add(bd);
		}
		return sum.doubleValue();
	}
	public static double process2(List<Number> list) {
		return 0;
	}
	
	public static void printList1(List<Object> list){
		for (Object elem : list)
	        System.out.println(elem + " ");
	    System.out.println();
	}
	
	public static void printList2(List<? extends Object> list) {
		//上边界符List<? extends Object> 接受 Object或Object子类的List。其实就是可以接受任意类型的List
		for (Object elem : list)
	        System.out.println(elem + " ");
	    System.out.println();
	}
	
	public static void printList3(List<?> list) {
		//无边界符List<?> 与List<? extends Object>等价的
		for (Object elem : list)
	        System.out.println(elem + " ");
	    System.out.println();
	}
	
	public static void addNumbers(List<? super Integer> list) {
		//To maximize flexibility
		for(int i=0;i<=10;i++) {
			list.add(i);
		}
	}
	
	public static void main(String[] args) {
		List<Integer> l1 = new ArrayList<>();
		l1.add(1);
		l1.add(2);
		System.out.println(process1(l1));
		
		List<Double> l2 = new ArrayList<>();
		l2.add(1.1);
		l2.add(2.2);
		System.out.println(process1(l2));
		
		//编译报错，类型不匹配，List<Integer>,List<Double> 类型不赋值给List<Number>类型
		//process2(l1); 
		//process2(l2);
		
		//编译报错，类型不匹配，List<Integer>类型不能赋值给List<Object>类型
		//printList1(l1);
		
		
		printList2(l2);
		printList3(l2);
		
		List<Number> l3 = new ArrayList<>();
		addNumbers(l1);
		addNumbers(l3);
		
		printList3(l1);
		printList3(l3);
		
	}
}
